package com.mazaiting.redeye.utils.confuse;

import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.util.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;

/***
 *
 *
 *                                                    __----~~~~~~~~~~~------___
 *                                   .  .   ~~//====......          __--~ ~~
 *                   -.            \_|//     |||\\  ~~~~~~::::... /~
 *                ___-==_       _-~o~  \/    |||  \\            _/~~-
 *        __---~~~.==~||\=_    -_--~/_-~|-   |\\   \\        _/~
 *    _-~~     .=~    |  \\-_    '-~7  /-   /  ||    \      /
 *  .~       .~       |   \\ -_    /  /-   /   ||      \   /
 * /  ____  /         |     \\ ~-_/  /|- _/   .||       \ /
 * |~~    ~~|--~~~~--_ \     ~==-/   | \~--===~~        .\
 *          '         ~-|      /|    |-~\~~       __--~~
 *                      |-~~-_/ |    |   ~\_   _-~            /\
 *                           /  \     \__   \/~                \__
 *                       _--~ _/ | .-~~____--~-/                  ~~==.
 *                      ((->/~   '.|||' -_|    ~~-/ ,              . _||
 *                                 -_     ~\      ~~---l__i__i__i--~~_/
 *                                 _-~-__   ~)  \--______________--~~
 *                               //.-~~~-~_--~- |-------~~~~~~~~
 *                                      //.-~~~--\
 *                               神兽保佑
 *                              代码无BUG!
 * @author mazaiting
 * @date 2019-06-24
 * @decription AES 加密工具类
 */
public class AesUtil {
    /**
     * 加密算法
     */
    private static final String AES = "AES";
    /**
     * 加密算法/模式/补码模式
     */
    private static final String AES_ECB_PKCS5PADDING = "AES/ECB/PKCS5Padding";
    /**
     * 加密 KEY
     */
    private static final String KEY = "0123456789abcdef";

    /**
     * 加密
     *
     * @param text 待加密文本
     * @return 加密后的字符串
     * @throws Exception 加密异常
     */
    public static String encrypt(String text) throws Exception {
        return encrypt(text, KEY);
    }

    /**
     * 加密
     *
     * @param text 待加密文本
     * @param key  KEY
     * @return 加密后的字符串
     * @throws Exception 加密异常
     */
    public static String encrypt(String text, String key) throws Exception {
        // 加密
        byte[] bytes = common(text, key, Cipher.ENCRYPT_MODE);
        // Base64 编码
        return Base64.encodeBase64String(bytes);
    }

    /**
     * 解密
     *
     * @param text 待解密文本
     * @return 解密后的字符串
     * @throws Exception 解密异常
     */
    public static String decrypt(String text) throws Exception {
        return decrypt(text, KEY);
    }


    /**
     * 解密
     *
     * @param text 待解密文本
     * @param key  KEY
     * @return 解密后的字符串
     * @throws Exception 解密异常
     */
    public static String decrypt(String text, String key) throws Exception {
        // 获取数据
        byte[] bytes = common(text, key, Cipher.DECRYPT_MODE);
        // 创建字符串
        return new String(bytes, Charset.defaultCharset());
    }

    /**
     AES 公共代码
     * @param text 待加密或解密的数据
     * @param key 密钥
     * @param mode 加密/解密
     * @return 二进制数据
     * @throws Exception
     */
    private static byte[] common(String text, String key, int mode) throws Exception {
        // 检测 KEY 值是否为空
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("Key 值不能为空");
        }
        // 判断 Key 值长度是否为 16
        if (key.length() != 16) {
            throw new RuntimeException("Key长度不是16位");
        }
        // 获取 KEY 字节
        byte[] keys = key.getBytes(Charset.defaultCharset());
        // 密钥规范
        SecretKeySpec keySpec = new SecretKeySpec(keys, AES);
        // 获取加密工具
        Cipher cipher = Cipher.getInstance(AES_ECB_PKCS5PADDING);
        // 初始化
        cipher.init(mode, keySpec);
        if (mode == Cipher.ENCRYPT_MODE) {
            // 加密
            return cipher.doFinal(text.getBytes(Charset.defaultCharset()));
        } else if (mode == Cipher.DECRYPT_MODE) {
            // 解密
            return cipher.doFinal(Base64.decodeBase64(text));
        } else {
            return null;
        }

    }
}
